package com.lagou.xm.io.sqlsession;

import com.lagou.xm.io.pojo.Configuration;

import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

/**
 * @author XM, Email is huangwei_xm@163.com
 * @ClassName SqlSessionImpl
 * @Package com.lagou.xm.io.sqlsession
 * @Description 实现SqlSession CURD
 * @Copyright: 训练营
 * @since 2020/9/25 1:24
 */
public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <E> List<E> selectList(String statementId, Object... params) throws SQLException {
        Executor executor = new SimpleExecutor();
        return executor.query(configuration, configuration.getSqlStatementMap().get(statementId), params);
    }

    @Override
    public <E> E selectOne(String statementId, Object... params) throws SQLException {
        List<Object> objects = this.selectList(statementId, params);
        if (objects.size() == 1) {
            return (E) objects.get(0);
        } else if (objects.size() > 1) {
            throw new RuntimeException("数据异常:查询结果为多条记录，请检查谢谢。");
        }
        return null;
    }

    @Override
    public <T> T getMapper(Class<T> clazz) {
        Object o = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 获取statementId
                String className = method.getDeclaringClass().getName();
                String methodName = method.getName();
                String statementId = className + "." + methodName;
                Type genericReturnType = method.getGenericReturnType();
                if (genericReturnType instanceof ParameterizedType) {
                    // 返回为集合
                    return selectList(statementId, args);
                } else {
                    // 返回对象
                    return selectOne(statementId, args);
                }
            }
        });
        return (T) o;
    }
}
